package com.plian.system.controller.qg.guarantee;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.plian.Tools.*;
import com.plian.Tools.base.BaseController;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.annotation.LogOperation;
import com.plian.system.common.status.CustomCode;
import com.plian.system.config.Resubmit;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.dto.qg.guarantee.PropertyGuaranteeApplyDTO;
import com.plian.system.entity.qg.guarantee.PropertyGuaranteeApply;
import com.plian.system.entity.qg.guarantee.PropertyGuaranteeAudit;
import com.plian.system.entity.qg.guarantee.PropertyGuaranteeWarrantee;
import com.plian.system.model.CommonCode;
import com.plian.system.model.ListResult;
import com.plian.system.model.ObjResult;
import com.plian.system.mybatis.search.SearchEntity;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.search.TokenSearch;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.service.qg.guarantee.IPropertyGuaranteeApplyService;
import com.plian.system.service.qg.guarantee.IPropertyGuaranteeAuditService;
import com.plian.system.service.qg.guarantee.IPropertyGuaranteeWarranteeService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.qg.guarantee.PropertyGuaranteeApplyVO;
import com.plian.system.vo.report.ReportReturnVO;
import com.plian.system.wrapper.qg.guarantee.PropertyGuaranteeApplyWrapper;
import com.plian.system.wrapper.qg.guarantee.PropertyGuaranteeAuditWrapper;
import com.plian.system.wrapper.qg.guarantee.PropertyGuaranteeWarranteeWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

/**
 * 企业担保申请主表 控制器
 *
 * @author jianglei
 * @since 2019-10-23
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("api/propertyguaranteeapply")
public class PropertyGuaranteeApplyController extends BaseController {

    private IPropertyGuaranteeApplyService propertyGuaranteeApplyService;

    private IPropertyGuaranteeAuditService propertyGuaranteeAuditService;

    private IPropertyGuaranteeWarranteeService propertyGuaranteeWarranteeService;

    private PropertyGuaranteeApplyWrapper propertyGuaranteeApplyWrapper;

    private PropertyGuaranteeAuditWrapper propertyGuaranteeAuditWrapper;

    private PropertyGuaranteeWarranteeWrapper propertyGuaranteeWarranteeWrapper;

    private FormWorkflowService formWorkflowService;

    /**
     * 详情
     */
    @PostMapping("/detail")
    public ObjResult detail(@Valid @RequestBody PropertyGuaranteeApply propertyGuaranteeApply) {
        ObjResult objResult;

        try {
            PropertyGuaranteeApply detail = propertyGuaranteeApplyService.getOne(Condition.getQueryWrapper(propertyGuaranteeApply));
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(detail).isPresent()) {
                PageData pd = new PageData();
                PropertyGuaranteeAudit propertyGuaranteeAudit = new PropertyGuaranteeAudit();
                propertyGuaranteeAudit.setPropertyGuaranteeApplyId(detail.getId());
                pd.put("propertyGuaranteeAudits",
                        propertyGuaranteeAuditWrapper.entityToVO(propertyGuaranteeAuditService.list(Condition.getQueryWrapper(propertyGuaranteeAudit))));

                PropertyGuaranteeWarrantee propertyGuaranteeWarrantee = new PropertyGuaranteeWarrantee();
                propertyGuaranteeWarrantee.setPropertyGuaranteeApplyId(detail.getId());
                pd.put("propertyGuaranteeWarrantees",
                        propertyGuaranteeWarranteeWrapper.entityToVO(propertyGuaranteeWarranteeService.list(Condition.getQueryWrapper(propertyGuaranteeWarrantee))));

                PropertyGuaranteeApplyVO propertyGuaranteeApplyVO = propertyGuaranteeApplyWrapper.entityToVO(detail);
                ObjectMapper mapper = new ObjectMapper();
                String json = JSON.toJSONStringWithDateFormat(propertyGuaranteeApplyVO, DateUtil.PATTERN_DATETIME);
                pd.putAll(mapper.readValue(json, new TypeReference<HashMap<String, String>>() {
                }));

                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }

        return objResult;
    }

    /**
     * 分页 企业担保申请主表
     */
    @PostMapping("/list")
    public ListResult<PropertyGuaranteeApplyVO> list(@Valid @RequestBody Query query) {
        if (query.getAscs() == null && query.getDescs() == null) {
            query.setDescs("create_time");
        }
        List<SearchEntity> entityList = query.getSearch();
        QueryWrapper<PropertyGuaranteeApply> queryWrapper = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new PropertyGuaranteeApply()), entityList
        );
        TokenSearch<PropertyGuaranteeApply> tokenSearch = new TokenSearch<>();
        tokenSearch.addTokenQuery(queryWrapper, query);
        IPage<PropertyGuaranteeApply> pages = propertyGuaranteeApplyService.page(Condition.getPage(query), queryWrapper);
        List<PropertyGuaranteeApplyVO> propertyGuaranteeApplyVOS = propertyGuaranteeApplyWrapper.entityToVO(pages.getRecords());
        ListResult<PropertyGuaranteeApplyVO> listResult = new ListResult<>(CommonCode.SUCCESS);
        listResult.setList(propertyGuaranteeApplyVOS);
        listResult.setTotal(Long.valueOf(pages.getTotal()).intValue());
        return listResult;
    }

    /**
     * 新增或修改 企业担保申请主表
     */
    @PostMapping("/submit")
    @LogOperation("企业担保申请-提交")
    @Resubmit(delaySeconds = 0)
    public ObjResult submit(@Valid @RequestBody PropertyGuaranteeApply propertyGuaranteeApply) {
        if (StringUtil.isBlank(propertyGuaranteeApply.getUnitRankId())) {
            return new ObjResult(CustomCode.builder().message("企业级次未找到，请先通过【产权变更】完善相关产权信息！").code(1999).success(false).build());
        }
        if (Optional.ofNullable(propertyGuaranteeApply.getStatus()).isPresent() &&
                propertyGuaranteeApply.getStatus() != FormStatusConstant.STASH) {
            if (StringUtil.isBlank(propertyGuaranteeApply.getWarranteeCompanyName())) {
                return new ObjResult(CustomCode.builder().message("被担保人为空").code(1999).success(false).build());
            }

            if (!propertyGuaranteeApplyService.checkIsExisted(propertyGuaranteeApply.getId(), propertyGuaranteeApply.getCode())) {
                return new ObjResult(CustomCode.builder().message("单据编码已存在").code(1999).success(false).build());
            }
        }

        ObjResult objResult = propertyGuaranteeApplyService.submit(propertyGuaranteeApply)
                ? new ObjResult(CommonCode.SUCCESS) : new ObjResult(CommonCode.FAIL);

        HashMap<String, Object> processVariable = new HashMap<>();
        formWorkflowService.startProcessAndSimulate(String.valueOf(propertyGuaranteeApply.getId()), propertyGuaranteeApply.getFormType(), processVariable);

        return objResult;
    }

    /**
     * 删除 企业担保申请主表
     */
    @PostMapping("/remove")
    @LogOperation("企业担保申请-删除")
    public ObjResult remove(@RequestBody PageData pd) {
        List<String> ids = (List<String>) pd.get("ids");
        return propertyGuaranteeApplyService.deleteLogic(Func.toLongList(StringUtils.join(ids, StringPool.COMMA)))
                ? new ObjResult(CommonCode.SUCCESS) : new ObjResult(CommonCode.FAIL);
    }

    /**
     * 申请担保单位汇总表
     */
    @PostMapping("/unitSummary")
    public ObjResult guaranteeUnitSummary(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            ReportReturnVO reportReturnVO = propertyGuaranteeApplyService.guaranteeUnitSummary(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(reportReturnVO).isPresent()) {
                PageData pd = new PageData();
                pd.put("grids", reportReturnVO.getGrids());
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }

        return objResult;
    }

    /**
     * 担保人汇总表
     */
    @PostMapping("/guaranteeSummary")
    public ObjResult guaranteeSummary(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            ReportReturnVO reportReturnVO = propertyGuaranteeApplyService.guaranteeSummary(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(reportReturnVO).isPresent()) {
                PageData pd = new PageData();
                pd.put("grids", reportReturnVO.getGrids());
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }

        return objResult;
    }

    /**
     * 被担保人汇总表
     */
    @PostMapping("/warranteeSummary")
    public ObjResult warranteeSummary(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            ReportReturnVO reportReturnVO = propertyGuaranteeApplyService.warranteeSummary(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(reportReturnVO).isPresent()) {
                PageData pd = new PageData();
                pd.put("grids", reportReturnVO.getGrids());
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }

        return objResult;
    }


    /**
     * 担保项目及年度对比分析
     */
    @PostMapping("/guaranteeAnnualAnalysis")
    public ObjResult guaranteeAnnualAnalysis(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            ReportReturnVO reportReturnVO = propertyGuaranteeApplyService.guaranteeAnnualAnalysis(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(reportReturnVO).isPresent()) {
                PageData pd = new PageData();
                pd.put("charts", reportReturnVO.getCharts());
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }

        return objResult;
    }

    /**
     * 获取所有已审核项目
     */
    @GetMapping("/getAll")
    public ListResult<PropertyGuaranteeApplyVO> getAll() {
        LambdaQueryWrapper<PropertyGuaranteeApply> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PropertyGuaranteeApply::getStatus, FormStatusConstant.FINISH);
        List<PropertyGuaranteeApply> propertyGuaranteeApplies = propertyGuaranteeApplyService.list(queryWrapper);
        List<PropertyGuaranteeApplyVO> propertyGuaranteeApplyVOS = propertyGuaranteeApplyWrapper.entityToVO(propertyGuaranteeApplies);
        ListResult<PropertyGuaranteeApplyVO> listResult = new ListResult<>(CommonCode.SUCCESS);
        listResult.setList(propertyGuaranteeApplyVOS);
        return listResult;
    }

    /**
     * 分页 企业担保申请主表
     */
    @PostMapping("/refList")
    public ListResult<PropertyGuaranteeApplyVO> refList(@Valid @RequestBody Query query) {
        if (query.getAscs() == null && query.getDescs() == null) {
            query.setDescs("create_time");
        }
        List<SearchEntity> entityList = query.getSearch();
        QueryWrapper<PropertyGuaranteeApply> queryWrapper = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new PropertyGuaranteeApply()), entityList
        );
        queryWrapper.eq("create_company_id", TokenUtil.getTokenOrgId());
        queryWrapper.eq("status", FormStatusConstant.FINISH);
        queryWrapper.gt("guarantee_remain", 0);

        IPage<PropertyGuaranteeApply> pages = propertyGuaranteeApplyService.page(Condition.getPage(query), queryWrapper);
        List<PropertyGuaranteeApplyVO> propertyGuaranteeApplyVOS = propertyGuaranteeApplyWrapper.entityToVO(pages.getRecords());
        ListResult<PropertyGuaranteeApplyVO> listResult = new ListResult<>(CommonCode.SUCCESS);
        listResult.setList(propertyGuaranteeApplyVOS);
        listResult.setTotal(Long.valueOf(pages.getTotal()).intValue());
        return listResult;
    }

    /**
     * 项目担保时间分析
     *
     * @param propertyGuaranteeApplyDTO
     * @return
     */
    @PostMapping("/guaranteeDateAnalysis")
    public ObjResult guaranteeDateAnalysis(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            PageData pd = propertyGuaranteeApplyService.guaranteeDateAnalysis(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(pd).isPresent()) {
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }
        return objResult;
    }

    /**
     * 项目担保金额分析
     *
     * @param propertyGuaranteeApplyDTO
     * @return
     */
    @PostMapping("/guaranteeAmountTotalAnalysis")
    public ObjResult guaranteeAmountTotalAnalysis(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            PageData pd = propertyGuaranteeApplyService.guaranteeAmountTotalAnalysis(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(pd).isPresent()) {
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }
        return objResult;
    }

    /**
     * 企业级次分析
     *
     * @param propertyGuaranteeApplyDTO
     * @return
     */
    @PostMapping("/unitRankIdAnalysis")
    public ObjResult unitRankIdAnalysis(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            PageData pd = propertyGuaranteeApplyService.unitRankIdAnalysis(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(pd).isPresent()) {
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }
        return objResult;
    }

    /**
     * 担保方式分析
     *
     * @param propertyGuaranteeApplyDTO
     * @return
     */
    @PostMapping("/guaranteeModeIdAnalysis")
    public ObjResult guaranteeModeIdAnalysis(@Valid @RequestBody(required = false) PropertyGuaranteeApplyDTO propertyGuaranteeApplyDTO) {
        ObjResult objResult;
        try {
            PageData pd = propertyGuaranteeApplyService.guaranteeModeIdAnalysis(propertyGuaranteeApplyDTO);
            objResult = new ObjResult(CommonCode.SUCCESS);
            if (Optional.ofNullable(pd).isPresent()) {
                objResult.setPageData(pd);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            objResult = new ObjResult(CommonCode.ERROR);
            return objResult;
        }
        return objResult;
    }
}
